﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ExpressionEvaluator
{
	/// <summary>
	/// Represent one code block.
	/// </summary>
	public class CodeBlock
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="CodeBlock"/> class.
		/// </summary>
		/// <param name="text">The text.</param>
		/// <param name="codeType">Type of the code.</param>
		/// <param name="startIndex">The start index.</param>
		/// <param name="length">The length.</param>
		internal CodeBlock(string text, CodeTypeEnum codeType, int startIndex, int length)
		{
			Text = text;
			CodeType = codeType;
			StartIndex = startIndex;
			Lenght = length;
			CorrectTextBasedOnType();
		}

		/// <summary>
		/// Corrects the type of the text based on.
		/// </summary>
		private void CorrectTextBasedOnType()
		{
			if (CodeType == CodeTypeEnum.Text)
			{
				Text = Regex.Replace(Text, @"(\\\\)|(\\\"")", match =>
				{
					if (!string.IsNullOrEmpty(match.Groups[1].Value))
						return "\\";
					else
						return "\"";
				});
			}
		}

		/// <summary>
		/// Gets the type of the code.
		/// </summary>
		/// <value>The type of the code.</value>
		public CodeTypeEnum CodeType
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the text of the code.
		/// </summary>
		/// <value>The text of the code.</value>
		public string Text
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the start index of code block in code.
		/// </summary>
		/// <value>The start index of code block in code.</value>
		public int StartIndex
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the lenght of code block in code.
		/// </summary>
		/// <value>The lenght of code block in code.</value>
		public int Lenght
		{
			get;
			private set;
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		public override string ToString()
		{
			return string.Format("{0} [{1}]", Text, CodeType);
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
		/// </returns>
		/// <exception cref="T:System.NullReferenceException">
		/// The <paramref name="obj"/> parameter is null.
		/// </exception>
		public override bool Equals(object obj)
		{
			if (obj is CodeBlock)
			{
				return this.GetHashCode() == obj.GetHashCode();
			}
			return base.Equals(obj);
		}

		/// <summary>
		/// Serves as a hash function for a particular type.
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"/>.
		/// </returns>
		public override int GetHashCode()
		{
			return Text.GetHashCode() ^ CodeType.GetHashCode();
		}
	}
}
